//Copyright 2010 Balazs Keri, Imre Keri
//
//This file is part of FireworksCreator.
//
//FireworksCreator is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//FireworksCreator is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with FireworksCreator.  If not, see <http://www.gnu.org/licenses/>.
//
#include "emitter.h"
#include <model/emittertemplate.h>
#include "particlesystem.h"
#include "controller.h"
//
namespace player
{
using namespace model;
Emitter::Emitter()
:
   emitter_template(0),
   controller(0)
{
}
Emitter::~Emitter()
{
   qDebug()<<"Player::Emitter::~Emitter";
}
void Emitter::init_setup(Controller *p_controller,const EmitterTemplate *p_emitter_template)
{
   Q_ASSERT(!emitter_template&&!controller);
   emitter_template=p_emitter_template;
   controller=p_controller;
}
void Emitter::trigger(const ParticleParam &p_param)const
{
   ParticleParam p;
   p.position=p_param.position;
   p.time=p_param.time;
   for(QList<EmitterTemplate::EmitterBlock>::ConstIterator ebi=emitter_template->emitter_blocks.begin();ebi!=emitter_template->emitter_blocks.end();++ebi)
   {
      const EmitterTemplate::EmitterBlock &eb=*ebi;
      for(unsigned int i=0;i<eb.amount;++i)
      {
         osg::Vec3 new_position=eb.position.data().calculate();
         osg::Vec3 new_angle=eb.angle.data().calculate();
         osg::Vec3 new_angular_velocity=eb.angular_velocity.data().calculate();
         p.angle=p_param.angle+new_angle;
         p.angular_velocity=new_angular_velocity;
         get_final_velocity(p_param,new_position,new_angle,new_angular_velocity,p.velocity);
         p.velocity*=eb.scale.data().calculate();
         if(eb.particle)
         {
            controller->particle_system_for_template(eb.particle)->schedule_create(p);
            if(eb.emitter)
            {
               if(!eb.synchronized)
               {
                  osg::Vec3 new_position=eb.position.data().calculate();
                  osg::Vec3 new_angle=eb.angle.data().calculate();
                  osg::Vec3 new_angular_velocity=eb.angular_velocity.data().calculate();
                  p.angle=p_param.angle+new_angle;
                  p.angular_velocity=new_angular_velocity;
                  get_final_velocity(p_param,new_position,new_angle,new_angular_velocity,p.velocity);
                  p.velocity*=eb.scale.data().calculate();
               }
               controller->emitter_for_template(eb.emitter)->trigger(p);
            }
         }
         else
         {
            Q_ASSERT(eb.emitter);
            controller->emitter_for_template(eb.emitter)->trigger(p);
         }
      }
   }
}
void Emitter::get_final_velocity(const ParticleParam &p_param_in,const osg::Vec3 &p_position,const osg::Vec3 &p_angle,const osg::Vec3 &p_angular_velocity,osg::Vec3 &p_final_velocity)const
{
   //currently angular velocity is not taken into account
   //not sure about how to do this calculation and possibly does not improve the animation quality much
   using namespace osg;
   Matrix rot=Matrix::rotate(
      p_param_in.angle.x(),Vec3(1.0,0.0,0.0),
      p_param_in.angle.y(),Vec3(0.0,1.0,0.0),
      p_param_in.angle.z(),Vec3(0.0,0.0,1.0)
   );
   p_final_velocity=Matrix::transform3x3(rot,p_position);
   p_final_velocity+=p_param_in.velocity;
}
}
